﻿#region using statements

using System;

using Microsoft.Xna.Framework;

using NGen;
using NGen.Managers.Audio;
using NGen.Managers.GUI;
using NGen.Managers.GameState;

using Nuclex.UserInterface;
using Nuclex.UserInterface.Controls;
using Nuclex.UserInterface.Controls.Desktop;

using Psych.States;

#endregion

namespace Psych.GUILayouts
{
    internal class GUIElementSettings : GUIElement
    {
        #region local fields

        private readonly ButtonControl m_audioButton = new ButtonControl();

        private readonly LabelControl m_audioMusicValueLabel1 = new LabelControl();

        private readonly LabelControl m_audioMusicValueLabel2 = new LabelControl();

        private readonly HorizontalSliderControl m_audioMusicVolumeSlider = new HorizontalSliderControl();

        private readonly LabelControl m_audioSoundValueLabel1 = new LabelControl();

        private readonly LabelControl m_audioSoundValueLabel2 = new LabelControl();

        private readonly HorizontalSliderControl m_audioSoundVolumeSlider = new HorizontalSliderControl();

        private readonly ButtonControl m_backMainButton = new ButtonControl();

        private readonly ButtonControl m_gameplayButton = new ButtonControl();

        private readonly ButtonControl m_otherBackButton = new ButtonControl();

        private readonly ButtonControl m_quitButton = new ButtonControl();

        private readonly ButtonControl m_startoverButton = new ButtonControl();

        private readonly LabelControl m_videoAntialiasingLabel = new LabelControl();

        private readonly ListControl m_videoAntialiasingList = new ListControl();

        private readonly ButtonControl m_videoApplyButton = new ButtonControl();

        private readonly ButtonControl m_videoButton = new ButtonControl();

        private readonly OptionControl m_videoFullscreenOption = new OptionControl();

        private readonly LabelControl m_videoResolutionLabel = new LabelControl();

        private readonly ListControl m_videoResolutionList = new ListControl();

        private readonly OptionControl m_videoVsyncOption = new OptionControl();

        private readonly WindowControl m_window = new WindowControl();

        #endregion

        #region local methods

        private void _ConfigureMainWindow(object p_sender, EventArgs p_e)
        {
            m_window.Children.Clear();
            m_window.Children.Add(m_backMainButton);
            m_window.Children.Add(m_audioButton);
            m_window.Children.Add(m_videoButton);
            m_window.Children.Add(m_quitButton);
            m_window.Children.Add(m_gameplayButton);
            m_window.Children.Add(m_startoverButton);
        }

        private void _ConfigureAudioWindow(object p_sender, EventArgs p_e)
        {
            m_window.Children.Clear();
            m_window.Children.Add(m_otherBackButton);
            m_window.Children.Add(m_audioMusicVolumeSlider);
            m_window.Children.Add(m_audioSoundVolumeSlider);
        }

        private void _ConfigureVideoWindow(object p_sender, EventArgs p_e)
        {
            m_window.Children.Clear();
            m_window.Children.Add(m_otherBackButton);
            m_window.Children.Add(m_videoResolutionLabel);
            m_window.Children.Add(m_videoResolutionList);
            m_videoResolutionList.SelectedItems.Clear();
            switch (GameEngine.GraphicsDeviceManager.PreferredBackBufferWidth)
            {
                case 800:
                    m_videoResolutionList.SelectedItems.Add(0);
                    break;
                case 1280:
                    m_videoResolutionList.SelectedItems.Add(1);
                    break;
                case 1440:
                    m_videoResolutionList.SelectedItems.Add(2);
                    break;
            }
            m_window.Children.Add(m_videoFullscreenOption);
            m_videoFullscreenOption.Selected = GameEngine.GraphicsDeviceManager.IsFullScreen;
            m_window.Children.Add(m_videoVsyncOption);
            m_videoVsyncOption.Selected = GameEngine.GraphicsDeviceManager.SynchronizeWithVerticalRetrace;
            m_window.Children.Add(m_videoAntialiasingList);
            m_window.Children.Add(m_videoAntialiasingLabel);
            m_videoAntialiasingList.SelectedItems.Clear();
            m_videoAntialiasingList.SelectedItems.Add(GameEngine.GraphicsDeviceManager.GraphicsDevice.PresentationParameters.MultiSampleCount == 0 ? 0 : (int)(Math.Log(GameEngine.GraphicsDeviceManager.GraphicsDevice.PresentationParameters.MultiSampleCount) / Math.Log(2)));

            m_window.Children.Add(m_videoApplyButton);
        }

        private void _ConfigureGameplayWindow(object p_sender, EventArgs p_e)
        {
            m_window.Children.Clear();
            m_window.Children.Add(m_otherBackButton);
        }

        private void _MusicSliderMoved(object p_sender, EventArgs p_e)
        {
            GameEngine.GetService<IManagerAudio2D>().SongVolume = m_audioMusicVolumeSlider.ThumbPosition;
            m_audioMusicValueLabel2.Text = Math.Floor(GameEngine.GetService<IManagerAudio2D>().SongVolume * 100.0f).ToString() + "%";
            m_audioMusicValueLabel2.Bounds = new UniRectangle(new UniScalar(0.5f, -0.5f * m_audioMusicValueLabel2.Text.Length * 5.0f), new UniScalar(1.5f, 0.0f), 0, 0);
        }

        private void _SoundSliderMoved(object p_sender, EventArgs p_e)
        {
            GameEngine.GetService<IManagerAudio2D>().SoundEffectVolume = m_audioSoundVolumeSlider.ThumbPosition;
            m_audioSoundValueLabel2.Text = Math.Floor(GameEngine.GetService<IManagerAudio2D>().SoundEffectVolume * 100.0f).ToString() + "%";
            m_audioSoundValueLabel2.Bounds = new UniRectangle(new UniScalar(0.5f, -0.5f * m_audioSoundValueLabel2.Text.Length * 5.0f), new UniScalar(1.5f, 0.0f), 0, 0);
        }

        private void _ApplyVideoSettings(object p_sender, EventArgs p_e)
        {
            switch (m_videoResolutionList.SelectedItems[0])
            {
                default:
                    GameEngine.GraphicsDeviceManager.PreferredBackBufferWidth = 800;
                    GameEngine.GraphicsDeviceManager.PreferredBackBufferHeight = 600;
                    break;
                case 1:
                    //not supported for this game
                    //GameEngine.GraphicsDeviceManager.PreferredBackBufferWidth = 1280;
                    //GameEngine.GraphicsDeviceManager.PreferredBackBufferHeight = 1024;
                    break;
                case 2:
                    //not supported for this game
                    //GameEngine.GraphicsDeviceManager.PreferredBackBufferWidth = 1440;
                    //GameEngine.GraphicsDeviceManager.PreferredBackBufferHeight = 900;
                    break;
            }
            GameEngine.GraphicsDeviceManager.GraphicsDevice.PresentationParameters.MultiSampleCount = m_videoAntialiasingList.SelectedItems[0] * 2;
            GameEngine.GraphicsDeviceManager.PreferMultiSampling = true;
            GameEngine.GraphicsDeviceManager.SynchronizeWithVerticalRetrace = m_videoVsyncOption.Selected;
            GameEngine.GraphicsDeviceManager.IsFullScreen = m_videoFullscreenOption.Selected;

            GameEngine.GraphicsDeviceManager.ApplyChanges();

            GameEngine.GameWindow.BeginScreenDeviceChange(m_videoFullscreenOption.Selected);
            GameEngine.GameWindow.EndScreenDeviceChange(GameEngine.GameWindow.ScreenDeviceName, GameEngine.GraphicsDeviceManager.PreferredBackBufferWidth, GameEngine.GraphicsDeviceManager.PreferredBackBufferHeight);
            GameEngine.GetService<IManagerGUI>().ScreenResolutionChanged();
        }

        #endregion

        #region GUIElement implmentation

        protected override void _Initialize()
        {
            m_window.EnableDragging = false;
            m_window.Bounds = new UniRectangle(new UniScalar(0.5f, -150.0f), new UniScalar(0.45f, -150.0f), new UniScalar(300.0f), new UniScalar(400));
            m_window.Title = "Options Window";
            _Children.Add(m_window);

            #region main settings window

            m_startoverButton.Bounds = new UniRectangle(new UniScalar(0.5f, -75.0f), new UniScalar(0.1f, 0.0f), new UniScalar(150), new UniScalar(40.0f));
            m_startoverButton.Text = "Start Over";
            m_startoverButton.Pressed += delegate { GameEngine.GetService<IManagerGameState>().ChangeState(new GameStatePlay(), true); };

            m_audioButton.Bounds = new UniRectangle(new UniScalar(0.5f, -75.0f), new UniScalar(0.25f, 0.0f), new UniScalar(150), new UniScalar(40.0f));
            m_audioButton.Text = "Audio Options";
            m_audioButton.Pressed += _ConfigureAudioWindow;

            m_videoButton.Bounds = new UniRectangle(new UniScalar(0.5f, -75.0f), new UniScalar(0.40f, 0.0f), new UniScalar(150), new UniScalar(40.0f));
            m_videoButton.Text = "Video Options";
            m_videoButton.Pressed += _ConfigureVideoWindow;
            m_gameplayButton.Bounds = new UniRectangle(new UniScalar(0.5f, -75.0f), new UniScalar(0.55f, 0.0f), new UniScalar(150), new UniScalar(40.0f));
            m_gameplayButton.Text = "Gameplay Options";
            m_gameplayButton.Pressed += _ConfigureGameplayWindow;

            m_quitButton.Bounds = new UniRectangle(new UniScalar(0.5f, -75.0f), new UniScalar(0.7f, 0.0f), new UniScalar(150), new UniScalar(40.0f));
            m_quitButton.Text = "Quit";
            m_quitButton.Pressed += delegate { GameEngine.GetService<IManagerGameState>().ChangeState(new GameStateMenu(), true); };

            m_backMainButton.Bounds = new UniRectangle(new UniScalar(0.9f, -55.0f), new UniScalar(0.9f, -12.5f), new UniScalar(55.0f), new UniScalar(25));
            m_backMainButton.Text = "Back";
            m_backMainButton.Pressed += delegate { GameEngine.GetService<IManagerGUI>().RemoveElement(this); };

            #endregion

            m_otherBackButton.Bounds = new UniRectangle(new UniScalar(0.9f, -55.0f), new UniScalar(0.9f, -12.5f), new UniScalar(55.0f), new UniScalar(25));
            m_otherBackButton.Text = "Back";
            m_otherBackButton.Pressed += _ConfigureMainWindow;
            _ConfigureMainWindow(this, null);

            #region audio window

            m_audioMusicVolumeSlider.Bounds = new UniRectangle(new UniScalar(0.5f, -75.0f), new UniScalar(0.3f, 0.0f), new UniScalar(150), new UniScalar(20.0f));
            m_audioMusicVolumeSlider.ThumbSize = 0.1f;
            m_audioMusicVolumeSlider.ThumbPosition = GameEngine.GetService<IManagerAudio2D>().SongVolume;
            m_audioMusicVolumeSlider.Moved += _MusicSliderMoved;

            m_audioMusicValueLabel1.Text = "Music Volume";
            m_audioMusicValueLabel1.Bounds = new UniRectangle(new UniScalar(0.5f, -0.5f * m_audioMusicValueLabel1.Text.Length * 7.0f), new UniScalar(-0.5f, 0.0f), 0, 0);
            m_audioMusicValueLabel2.Text = Math.Floor(GameEngine.GetService<IManagerAudio2D>().SongVolume * 100.0f).ToString() + "%";
            m_audioMusicValueLabel2.Bounds = new UniRectangle(new UniScalar(0.5f, -0.5f * m_audioMusicValueLabel2.Text.Length * 5.0f), new UniScalar(1.5f, 0.0f), 0, 0);

            m_audioMusicVolumeSlider.Children.Add(m_audioMusicValueLabel1);
            m_audioMusicVolumeSlider.Children.Add(m_audioMusicValueLabel2);

            m_audioSoundVolumeSlider.Bounds = new UniRectangle(new UniScalar(0.5f, -75.0f), new UniScalar(0.6f, 0.0f), new UniScalar(150), new UniScalar(20.0f));
            m_audioSoundVolumeSlider.ThumbSize = 0.1f;
            m_audioSoundVolumeSlider.ThumbPosition = GameEngine.GetService<IManagerAudio2D>().SoundEffectVolume;
            m_audioSoundVolumeSlider.Moved += _SoundSliderMoved;

            m_audioSoundValueLabel1.Text = "Sound Effects Volume";
            m_audioSoundValueLabel1.Bounds = new UniRectangle(new UniScalar(0.5f, -0.5f * m_audioSoundValueLabel1.Text.Length * 7.0f), new UniScalar(-0.5f, 0.0f), 0, 0);
            m_audioSoundValueLabel2.Text = Math.Floor(GameEngine.GetService<IManagerAudio2D>().SoundEffectVolume * 100.0f).ToString() + "%";
            m_audioSoundValueLabel2.Bounds = new UniRectangle(new UniScalar(0.5f, -0.5f * m_audioSoundValueLabel2.Text.Length * 5.0f), new UniScalar(1.5f, 0.0f), 0, 0);

            m_audioSoundVolumeSlider.Children.Add(m_audioSoundValueLabel1);
            m_audioSoundVolumeSlider.Children.Add(m_audioSoundValueLabel2);

            #endregion

            #region video window

            m_videoResolutionLabel.Text = "Screen Resolution:";
            m_videoResolutionLabel.Bounds = new UniRectangle(new UniScalar(0.1f, 0.0f), new UniScalar(0.08f, 0.0f), new UniScalar(100.0f), new UniScalar(0.1f, 0.0f));
            m_videoResolutionList.Bounds = new UniRectangle(new UniScalar(0.1f, 0.0f), new UniScalar(0.16f, 0.0f), new UniScalar(0.6f, 0.0f), new UniScalar(0.225f, 0.0f));
            m_videoResolutionList.Items.Add("800 x 600");
            m_videoResolutionList.Items.Add("1280 x 1024");
            m_videoResolutionList.Items.Add("1440 x 900");
            m_videoResolutionList.SelectionMode = ListSelectionMode.Single;

            m_videoFullscreenOption.Text = "Fullscreen";

            m_videoFullscreenOption.Bounds = new UniRectangle(new UniScalar(0.1f, 0.0f), new UniScalar(0.425f, 0.0f), new UniScalar(20.0f), new UniScalar(20.0f));

            m_videoVsyncOption.Text = "Vertical sync refresh rate";

            m_videoVsyncOption.Bounds = new UniRectangle(new UniScalar(0.1f, 0.0f), new UniScalar(0.51f, 0.0f), new UniScalar(20.0f), new UniScalar(20.0f));

            m_videoAntialiasingLabel.Text = "Antialiasing: (does not work)";
            m_videoAntialiasingLabel.Bounds = new UniRectangle(new UniScalar(0.1f, 0.0f), new UniScalar(0.55f, 0.0f), new UniScalar(0.0f), new UniScalar(0.1f, 0.0f));
            m_videoAntialiasingList.Bounds = new UniRectangle(new UniScalar(0.1f, 0.0f), new UniScalar(0.630f, 0.0f), new UniScalar(0.6f, 0.0f), new UniScalar(0.21f, 0.0f));
            m_videoAntialiasingList.Items.Add("none");
            m_videoAntialiasingList.Items.Add("2x");
            m_videoAntialiasingList.Items.Add("4x");
            m_videoAntialiasingList.Items.Add("8x");
            m_videoAntialiasingList.SelectionMode = ListSelectionMode.Single;

            m_videoApplyButton.Bounds = new UniRectangle(new UniScalar(0.2f, -27.5f), new UniScalar(0.9f, -12.5f), new UniScalar(55.0f), new UniScalar(25));
            m_videoApplyButton.Text = "Apply";
            m_videoApplyButton.Pressed += _ApplyVideoSettings;

            #endregion

            #region gameplay window

            #endregion
        }

        protected override void Update(GameTime p_gameTime) { }

        protected override void _Cleanup()
        {
            if (GameEngine.GetService<IManagerGameState>().CurrentStateName == "GameStatePause")
            {
                GameEngine.GetService<IManagerGameState>().PopState();
            }
        }

        #endregion
    }
}